/*******************************************************************************
 * This file is part of blueprint4j www.blueprint4j.org.
 * 
 *     blueprint4j is free software: you can redistribute it and/or modify
 *     it under the terms of the GNU Lesser General Public License as published by
 *     the Free Software Foundation, either version 3 of the License, or
 *     (at your option) any later version.
 * 
 *     blueprint4j is distributed in the hope that it will be useful,
 *     but WITHOUT ANY WARRANTY; without even the implied warranty of
 *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *     GNU Lesser General Public License for more details.
 * 
 *     You should have received a copy of the GNU Lesser General Public License
 *     along with blueprint4j. If not, see <http://www.gnu.org/licenses/>.
 ******************************************************************************/
package blueprint4j.db;

import blueprint4j.utils.BindException;
import blueprint4j.utils.BindStringSelectInterface;
import blueprint4j.utils.Log;


public class FieldForeignKeyChild extends FieldString implements BindStringSelectInterface,FieldForeignKeyInterface {
    
    private VectorEntity entity_list = new VectorEntity();
    private Class entity_foreign = null;
    private Entity parent = null;
    private String whereClause="1=1";
    private FieldForeignKey fieldForeignKey;
    private String childFieldForeignKeyName;
    private String childFieldForeignKeyTableName;
       
    /**
     */
    public FieldForeignKeyChild( String p_name, int p_field_type ,String p_description,int length,Class entity_foreign,FieldForeignKey fieldForeignKey,String childFieldForeignKeyName,String childFieldForeignKeyTableName,String whereClause,Entity entity_local) {
        super( p_name,p_field_type,p_description,length,entity_local );
        this.entity_foreign = entity_foreign;
        this.whereClause=whereClause;
        this.fieldForeignKey=fieldForeignKey;
        this.childFieldForeignKeyName=childFieldForeignKeyName;
        this.childFieldForeignKeyTableName=childFieldForeignKeyTableName;
    }

    public FieldForeignKeyChild( String p_name, int p_field_type ,String p_description,int length,Class entity_foreign,FieldForeignKey fieldForeignKey,String childFieldForeignKeyName,String childFieldForeignKeyTableName,Entity entity_local) {
    	this(p_name, p_field_type ,p_description,length,entity_foreign,fieldForeignKey,childFieldForeignKeyName,childFieldForeignKeyTableName,"1=1",entity_local);
    }
    
    public Field newInstance(Entity entity) {
        return new FieldForeignKeyChild(getName(),getFieldType(),getDescription(),getLength(),entity_foreign,(FieldForeignKey)entity.getFieldByName(fieldForeignKey.getName()),childFieldForeignKeyName,childFieldForeignKeyTableName,whereClause,entity);
    }
    
    public Class getForeignEntity() {
        return entity_foreign;
    }
    
    public Entity getNewForeignInstance() {
        try {
            return (Entity)(entity_foreign.newInstance().getClass().getConstructor(new Class[]{}).newInstance(new Object[]{}));
        } catch (Throwable th) {
            Log.critical.out(th);
            return null;
        }
    }

    public Field getField(){
    	return this;
    }
    
    protected Entity getNewEntity(DBConnection dbcon,Class en_class)
    throws DataException {
        try {
            return
                    (Entity)(en_class.newInstance().getClass().getConstructor(new Class[]{dbcon.getClass()}).newInstance(new Object[]{dbcon}));
        } catch (Exception exception) {
            exception.printStackTrace();
            throw new DataException(exception);
        }
    }
    
    public void setParentEntity(Entity parent) {
        this.parent = parent;
    }
    
        /*
        public Entity p(DBConnection dbcon)
        throws DataException {
                return getNewEnitty(dbcon,entity_foreign);
}*/
    
    public Entity getNewLocal(DBConnection dbcon)
    throws DataException {
        return getNewEntity(dbcon,getEntity().getClass());
    }
    
    public String get() {
        try {
            if (super.get() == null && parent != null) {
                if (parent.id.getAsString() != null) {
                    set(parent.id.getAsString());
                    return parent.id.getAsString();
                } else {
                    parent.save();
                    set(parent.id.getAsString());
                    return parent.id.getAsString();
                }
            }
            return super.get();
        } catch (Exception exception) {
            Log.debug.out(exception);
        }
        return null;
    }
    
    public void setAsString(String value) {
        set(value);
    }
    
    public String getAsString(){
        return get();
    }
    
    /**
     * This retrieves the foriegn entity related to this key
     * If no foreign relation had been defined then it creates a new instance
     * of that class
     */
    public Entity retrieve()
    throws DataException {
        try {
            if (get() == null || get().length() == 0 || entity_foreign==null || getEntity().getConnection()==null) {
                return null;
            }
            if (parent == null) {
                Entity new_entity = getNewEntity(getEntity().getConnection(),entity_foreign);
                new_entity.id.setAsString(get());
                new_entity.loadFromIdField();
                parent = new_entity;
            }
            return parent;
        } catch (Throwable throwable) {
            throw new DataException(throwable);
        }
    }
    
    /**
     * Return the current active display
     */
    public String getDisplay() {
        try {
            if (entity_list.get(get()) != null) {
                return entity_list.get(get()).getNameFields().toString(",");
            }
        } catch (Exception exception) {
            Log.debug.out(exception);
        }
        return null;
    }
    
    /**
     * Reloads the whole foreign entity set
     * Limits 50
     */
    public void refresh()
    throws BindException {
        try {
        	if (fieldForeignKey.retrieve()!=null){
	        	EntityChild ec=fieldForeignKey.retrieve().getChildByForeignKeyNameAndTable(childFieldForeignKeyName,childFieldForeignKeyTableName);
	            entity_list = new VectorEntity(getNewEntity(getEntity().getConnection(),entity_foreign).find(ec.getSqlWhere()+" and "+whereClause),50);
        	}
        } catch (Exception exception) {
            throw new BindException(exception);
        }
    }
    
    public String[] getOptions() {
        try {
            return entity_list.getId().toArray(new String[0]);
        } catch (Exception exception) {
            Log.debug.out(exception);
        }
        return null;
    }
    
    public String[] getDisplays() {
        return entity_list.getName().toArray(new String[0]);
    }    
}
